#pragma once

#include <iostream>
#include <string>
#include <memory>
#include <functional>

#include "Socket.hpp"
#include "ThreadPool.hpp"
#include "Log.hpp"

using namespace My_Log;
using namespace My_Socket;
using namespace My_ThreadPool;

using hander_t = std::function<void(SockPtr, InetAddr)>;
using threadpool_t = std::function<void()>;

class TcpServer
{
public:
    TcpServer(int port) : _port(port), _socket(std::make_unique<TcpSocket>())
    {
    }
    void InitServer(hander_t hander)
    {
        _hander = hander;
        _socket->BuildTcpSocket(_port);
    }
    void Loop()
    {
        LOG(LogLevel::DEBUG) << "running Loop";
        _isrunning = true;
        std::string recvstr;
        while (true)
        {
            InetAddr cliaddr;
            SockPtr sp = _socket->Accepter(&cliaddr);
            if (!sp)
            {
                break;
            }
            LOG(LogLevel::DEBUG) << "get a new client, info is: " << cliaddr.GetStrIpPort();
            ThreadPool<threadpool_t>::getinstance()->Equeue([this, cliaddr, sp]()
                                                            { this->_hander(sp, cliaddr); });
        }
    }
    hander_t GetHander() { return _hander; }
    ~TcpServer()
    {
        _socket->Close();
    }

private:
    std::unique_ptr<Socket> _socket;
    int _port;
    bool _isrunning;
    hander_t _hander;
};